/*
 * Sky.cpp
 *
 *  Created on: 21.11.2012
 *      Author: Travis
 */

#ifdef _WIN32 
#include <windows.h> 
#endif

#include "Sky.h"

Sky::Sky(float _high, float _size)
{
#ifdef _DEBUG
	std::cout << "SKY: Init" << std::endl;
#endif
	high = _high;
	size = _size;

	// loading textures and shaders for sky mesh
	textures = new TexPool(
			Engine::fileStructure.texturePath + Engine::mapFileStruct.skyPath);

	textures->loadDir();

	shaderID = Shader::sPool->getProgramID("sky"); // load shader program

	textureID = textures->getTexIdByName("sky.jpg");

	genVBO();
	genNormalBO();
	genUVBO();
}

Sky::~Sky()
{
	UVCoord.clear();
	vertices.clear();
	normals.clear();

	// delete buffers
	glDeleteBuffers(1, &VertexArrayID);
	glDeleteBuffers(1, &uvbuffer);
	glDeleteBuffers(1, &normalBufferID);
}

void Sky::genVBO()
{
	// setup vertices
	vertices = std::vector<glm::vec3>();
	vertices.push_back(glm::vec3(-size, high, -size));
	vertices.push_back(glm::vec3(size * 2, high, -size));
	vertices.push_back(glm::vec3(size * 2, high, size * 2));
	vertices.push_back(glm::vec3(-size, high, size * 2));

	glGenBuffers(1, &VertexArrayID);
	glBindBuffer(GL_ARRAY_BUFFER, VertexArrayID);
	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3),
			&vertices[0], GL_STATIC_DRAW);
}

void Sky::genUVBO()
{
	// setup UV Coord of texture
	UVCoord = std::vector<glm::vec2>();
	UVCoord.push_back(glm::vec2(0.0, 0.0));
	UVCoord.push_back(glm::vec2(0.0, 1.0));
	UVCoord.push_back(glm::vec2(1.0, 1.0));
	UVCoord.push_back(glm::vec2(1.0, 0.0));

	glGenBuffers(1, &uvbuffer);
	glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
	glBufferData(GL_ARRAY_BUFFER, UVCoord.size() * sizeof(glm::vec2), &UVCoord[0],
			GL_STATIC_DRAW);
}

void Sky::genNormalBO()
{
	// setup normal
	normals = std::vector<glm::vec3>();
	normals.push_back(glm::vec3(0.0, 1.0, 0.0));
	normals.push_back(glm::vec3(0.0, 1.0, 0.0));
	normals.push_back(glm::vec3(0.0, 1.0, 0.0));
	normals.push_back(glm::vec3(0.0, 1.0, 0.0));

	glGenBuffers(1, &normalBufferID);
	glBindBuffer(GL_ARRAY_BUFFER, normalBufferID);
	glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0],
			GL_STATIC_DRAW);
}

void Sky::draw()
{
	float time = (float) SDL_GetTicks() / 2000.0;

	// get matrix
	glm::mat4 ModelMatrix = glm::mat4(1.0);
	glm::mat4 ViewMatrix = World::world->getView();
	//ViewMatrix = glm::rotate(ViewMatrix,45.0f, glm::vec3(0.0f, 1.0f ,0.0f));
	glm::mat4 MVP = World::world->getProjection() * ViewMatrix * ModelMatrix;

	// get light information
	glm::vec3 LightPos = World::world->getLightPos(); // position of light
	glm::vec3 LightDif = World::world->getLightDif(); // diffuse color of light
	glm::vec3 LightAmb = World::world->getLightAmb(); // ambient color of light
	glm::vec3 LightSpec = World::world->getLightSpe(); // specular color of light

	glUseProgram(shaderID);

	// send matrix to shader

	glUniform1i(glGetUniformLocation(shaderID, "tex0"), 0);

	glUniform1f(glGetUniformLocation(shaderID, "time"), time);

	glUniformMatrix4fv(glGetUniformLocation(shaderID, "MVP"), 1, GL_FALSE,
			&MVP[0][0]);
	glUniformMatrix4fv(glGetUniformLocation(shaderID, "M"), 1, GL_FALSE,
			&ModelMatrix[0][0]);
	glUniformMatrix4fv(glGetUniformLocation(shaderID, "V"), 1, GL_FALSE,
			&ViewMatrix[0][0]);
	glUniform3f(glGetUniformLocation(shaderID, "LightPosition_worldspace"),
			LightPos.x, LightPos.y, LightPos.z);
	glUniform3f(glGetUniformLocation(shaderID, "lightAmb"), LightAmb.x,
			LightAmb.y, LightAmb.z);
	glUniform3f(glGetUniformLocation(shaderID, "lightDif"), LightDif.x,
			LightDif.y, LightDif.z);
	glUniform3f(glGetUniformLocation(shaderID, "lightSpec"), LightSpec.x,
			LightSpec.y, LightSpec.z);

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);

	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, VertexArrayID);
	glVertexAttribPointer(0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
			3, // size
			GL_FLOAT, // type
			GL_FALSE, // normalized?
			0, // stride
			(void*) 0 // array buffer offset
	);

	glEnableVertexAttribArray(1);
	glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
	glVertexAttribPointer(1, // attribute 0. No particular reason for 0, but must match the layout in the shader.
			2, // size
			GL_FLOAT, // type
			GL_FALSE, // normalized?
			0, // stride
			(void*) 0 // array buffer offset
	);

	glEnableVertexAttribArray(2);
	glBindBuffer(GL_ARRAY_BUFFER, normalBufferID);
	glVertexAttribPointer(2, // attribute 0. No particular reason for 0, but must match the layout in the shader.
			3, // size
			GL_FLOAT, // type
			GL_FALSE, // normalized?
			0, // stride
			(void*) 0 // array buffer offset
	);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, textureID);

	glDrawArrays(GL_QUADS, 0, 4);
	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
	glDisableVertexAttribArray(2);

	glDisable(GL_BLEND);

	glUseProgram(0);
}

float Sky::getHigh()
{
	return high;
}

